﻿using DGZImp.Core.Services;
using DGZImp.MdsProject.Base;
using DGZImp.MdsProject.Devices.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace DGZImp.MdsProject.Devices.Helper
{
    /// <summary>
    /// 获取设备可以下发指令的帮助类
    /// </summary>
    public class ActionHelper
    {
        public static List<DeviceActionInfo> GetActions(Type deviceType)
        {
            var actions = new List<DeviceActionInfo>();
            var methods = deviceType.GetMethods(BindingFlags.Public | BindingFlags.Instance);
            foreach (var method in methods)
            {
                var actionNameAttr = method.GetCustomAttribute<MdsActionAttribute>();
                if (actionNameAttr != null)
                {
                    var parameters = new List<ParameterDto>();
                    foreach (var item in method.GetParameters())
                    {
                        var descriptionAttribute = item.GetCustomAttribute<MdsParameterAttribute>();
                        string description = descriptionAttribute?.Description ?? item.Name;
                        var p = new ParameterDto
                        {
                            Name = item.Name,
                            Description = description,
                            Type = item.ParameterType.Name,
                            IsOptional = item.IsOptional,
                            Options = new List<ParameterOptionsItem>()
                        };
                        //如果item.ParameterType是整型，则Type赋值为int
                        if (p.Type == "Int32" || p.Type == "Int16" || p.Type == "Int64")
                        {
                            p.Type = "Int";
                        }
                        //如果p是浮点型，则Type赋值为decimal
                        if (p.Type == "Double" || p.Type == "Float" || p.Type == "Decimal")
                        {
                            p.Type = "Decimal";
                        }
                        //如果item.ParameterType的类型是枚举，则获取枚举的所有项，并添加到Options中(Label,Value)
                        if (item.ParameterType.IsEnum)
                        {
                            p.Type = "Select";
                            var enumValues = Enum.GetValues(item.ParameterType);
                            foreach (var value in enumValues)
                            {
                                var label = Enum.GetName(item.ParameterType, value);
                                var valueStr = Convert.ToInt32(value);
                                p.Options.Add(new ParameterOptionsItem { Label = label, Value = valueStr });
                            }
                        }
                        parameters.Add(p);
                    }
                    var actionInfo = new DeviceActionInfo
                    {
                        Name = actionNameAttr.Name,
                        Description = actionNameAttr.Description,
                        ActionName = method.Name,
                        Parameters = parameters.ToArray()
                    };
                    actions.Add(actionInfo);
                }
            }

            return actions;
        }

        public static async Task<object> ExecuteAction(object deviceInstance, string methodName, params object[] args)
        {
            var methodInfo = deviceInstance.GetType().GetMethod(methodName, BindingFlags.Public | BindingFlags.Instance);
            if (methodInfo == null)
            {
                throw new ArgumentException($"Method '{methodName}' not found.");
            }

            var parameters = methodInfo.GetParameters();
            var convertedArgs = new object[parameters.Length];

            for (int i = 0; i < parameters.Length; i++)
            {
                var parameterType = parameters[i].ParameterType;
                if (parameterType.IsEnum)
                {
                    convertedArgs[i] = Enum.Parse(parameterType, args[i].ToString());
                }
                else
                {
                    convertedArgs[i] = Convert.ChangeType(args[i], parameterType);
                }
            }

            var returnType = methodInfo.ReturnType;
            if (returnType == typeof(Task))
            {
                dynamic task = methodInfo.Invoke(deviceInstance, convertedArgs);
                await task.ConfigureAwait(false);
                return null;
            }
            else if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>))
            {
                dynamic task = methodInfo.Invoke(deviceInstance, convertedArgs);
                await task.ConfigureAwait(false);
                return task.Result;
            }
            else
            {
                return methodInfo.Invoke(deviceInstance, convertedArgs);
            }
        }

    }


    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    public class MdsActionAttribute : Attribute
    {
        public string Name { get; }
        public string Description { get; }

        public MdsActionAttribute(string name, string description)
        {
            Name = name;
            Description = description;
        }
    }

    [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)]
    public class MdsParameterAttribute : Attribute
    {
        public string Description { get; }

        public MdsParameterAttribute(string description)
        {
            Description = description;
        }
    }
}
